#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>

#include "lwip/init.h"
#include "lwip/pbuf.h"
#include "lwip/ip.h"
#include "lwip/tcp.h"
#include "lwip/tcpip.h"
#include "lwip/altcp.h"
#include "lwip/altcp_tcp.h"
#include "lwip/altcp_tls.h"
#include "lwip/err.h"
#include "lwip/timeouts.h"
#include "lwip/netif.h"
#include "lwip/init.h"
#include "netif/tapif.h"


#define CLIENT_CA_CERT_PEM \
    "-----BEGIN CERTIFICATE-----\r\n" \
    "MIIDzzCCAregAwIBAgIUMnfWZiXhuZbCaFkOLRiQSEI46rkwDQYJKoZIhvcNAQEL\r\n" \
    "BQAwbzELMAkGA1UEBhMCWFgxCzAJBgNVBAgMAlhYMQswCQYDVQQHDAJYWDEUMBIG\r\n" \
    "A1UECgwLY2VydGlmaWNhdGUxDzANBgNVBAsMBnRlc3RjYTEfMB0GA1UEAwwWY2Vy\r\n" \
    "dGlmaWNhdGUudGVzdGNhLmNvbTAeFw0yNDA0MjUxMzAxMDBaFw0zNDA0MjMxMzAx\r\n" \
    "MDBaMG8xCzAJBgNVBAYTAlhYMQswCQYDVQQIDAJYWDELMAkGA1UEBwwCWFgxFDAS\r\n" \
    "BgNVBAoMC2NlcnRpZmljYXRlMQ8wDQYDVQQLDAZ0ZXN0Y2ExHzAdBgNVBAMMFmNl\r\n" \
    "cnRpZmljYXRlLnRlc3RjYS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK\r\n" \
    "AoIBAQCZD4K/oBU7/DCThMTftZUazVd3NIjKHQcIO5Uul9F3gIOavMpqcT+epfy1\r\n" \
    "yUWny31DdG6ku3HJHT2zoqerYgqAh2ediFvnCAe+OzCrDOr3+9ZXt8vv1H2M6X1U\r\n" \
    "zF+tRaeZ3IgAJBiYBNbdoK4RtzYRfM+29tVp01NJguJza9bMw/qEiQQyubGhlVQi\r\n" \
    "IW109aYjhiA0RQl6814upi09vfECnzZ+2kkvmkuEEptBiDlE3tSEctJPNSbAN6mn\r\n" \
    "B3krKfLspcZaoRuJucI6duJeJQcsjQCIEjqgnVuOWoMVOAPLU7JPeOrubePbAySU\r\n" \
    "yNTPzntqJWs/j6Iacol6N3iJThjfAgMBAAGjYzBhMB0GA1UdDgQWBBSLzdFm06DU\r\n" \
    "ldtZ2btuIKMNjG1YjzAfBgNVHSMEGDAWgBSLzdFm06DUldtZ2btuIKMNjG1YjzAS\r\n" \
    "BgNVHRMBAf8ECDAGAQH/AgEeMAsGA1UdDwQEAwIBBjANBgkqhkiG9w0BAQsFAAOC\r\n" \
    "AQEALqPQ8BTMfMFBEvxN9wJzanH6M0FIt+LE0JvMPMBvflwu0GTL26+/Nqd2sQLx\r\n" \
    "mDByrx+8cFodY3squFBY1dFMwIsMyF8WK/Nh80ZGG8tjKrFlVXE2npRlf5VSkytk\r\n" \
    "FVz94lFjl0eP6rsUfUamRF2eNg76uoY7tZwTPNqA/zsoRN81n3ccr81CbfOyhPVB\r\n" \
    "XAse0651f3u76rm7NJNYSeR7qebMyfYrJBu7w/O3K4QCeGjZ3b76xNZtatw1ZXol\r\n" \
    "irzwVW71bsCftIj3Nu1WFmczr6habktQ7/PyR5hG/I8mh2lkZcZe1Fw3t4hGNAtW\r\n" \
    "oWDxfkMk0rSnsUcvOtvhfX5Bvw==\r\n"                                     \
    "-----END CERTIFICATE-----\r\n"                                        \
    "-----BEGIN CERTIFICATE-----\r\n"                                      \
    "MIIDnDCCAoSgAwIBAgIBATANBgkqhkiG9w0BAQsFADBvMQswCQYDVQQGEwJYWDEL\r\n" \
    "MAkGA1UECAwCWFgxCzAJBgNVBAcMAlhYMRQwEgYDVQQKDAtjZXJ0aWZpY2F0ZTEP\r\n" \
    "MA0GA1UECwwGdGVzdGNhMR8wHQYDVQQDDBZjZXJ0aWZpY2F0ZS50ZXN0Y2EuY29t\r\n" \
    "MB4XDTI0MDQyNTEzMDEwMFoXDTM0MDQyMzEzMDEwMFowYjELMAkGA1UEBhMCWFgx\r\n" \
    "CzAJBgNVBAgMAlhYMRQwEgYDVQQKDAtjZXJ0aWZpY2F0ZTEPMA0GA1UECwwGdGVz\r\n" \
    "dGluMR8wHQYDVQQDDBZjZXJ0aWZpY2F0ZS50ZXN0aW4uY29tMIIBIjANBgkqhkiG\r\n" \
    "9w0BAQEFAAOCAQ8AMIIBCgKCAQEA18rpiCfBpz44ZvBoELRoaCt1ddxSBI250Uj4\r\n" \
    "io1XUPhqJUmreEFc6vR32RvW6krspgYyx00pqH4nptJOVpOF7fGxANqmT3Dq7jyt\r\n" \
    "H91gha7GViTRe/NH52R3iGInCxsC+snaFH35MLzvaKUCg6Agrw0ozrykjHBrQtkj\r\n" \
    "zTvXkwexj/1lMW0FzF79z6SC9bfwLqYldfEgtEZTcTt0SJf6wLW4BeEUCnT+vMX1\r\n" \
    "hlbOjgI4tuh6RznmbffoxOb9ynJYJ8oPo5X1RN+DIMZ9KUj4DUAP/84x1uQj5cSQ\r\n" \
    "hERvnEBPWOEC2KhEUzsG97fH/axXg3+Aj8FJAkNp6BnWeKtG1wIDAQABo1AwTjAM\r\n" \
    "BgNVHRMEBTADAQH/MB0GA1UdDgQWBBTgYJN/ObsFIRlEELDAKWSitrsjEjAfBgNV\r\n" \
    "HSMEGDAWgBSLzdFm06DUldtZ2btuIKMNjG1YjzANBgkqhkiG9w0BAQsFAAOCAQEA\r\n" \
    "Q0MFGy3ZfYaBqSIUBwBq1bbADM0mTj3kjeDz7qBKQu4Krfvpzlp7VqD1T3bldgwR\r\n" \
    "T0gBzWAZnbQ77fBZnCnaz7ZbK0mIin5eT2s9QCOgPY0u6P8oFH56Guet86ly9gSU\r\n" \
    "yako9lzyYxaJrWpWAmMw7zAzWWLtIiTjciQ7Wi4ihTPbAloUvEIyIWHNs39hNHWF\r\n" \
    "hBr121y0WDbcNpScFd2ZY+Z4T3Bzs8K3rhX+Gxr118qhXYSLsjlm2kkG6y68e8U2\r\n" \
    "9BeiW15gWirCLtKVv/fUdOoMcVbjpr7QYtK8iOOyumjxSn9KOevJ/V6p30ZyCuuz\r\n" \
    "FbPbbv2clmJvtygezDOZxA==\r\n" \
    "-----END CERTIFICATE-----"

#define CLIENT_CERT_PEM \
    "-----BEGIN CERTIFICATE-----\r\n" \
    "MIIDkjCCAnqgAwIBAgIBBDANBgkqhkiG9w0BAQsFADBiMQswCQYDVQQGEwJYWDEL\r\n" \
    "MAkGA1UECAwCWFgxFDASBgNVBAoMC2NlcnRpZmljYXRlMQ8wDQYDVQQLDAZ0ZXN0\r\n" \
    "aW4xHzAdBgNVBAMMFmNlcnRpZmljYXRlLnRlc3Rpbi5jb20wHhcNMjQwNTA1MDkz\r\n" \
    "NzQ5WhcNMzQwNTAzMDkzNzQ5WjBoMQswCQYDVQQGEwJYWDELMAkGA1UECAwCWFgx\r\n" \
    "FDASBgNVBAoMC2NlcnRpZmljYXRlMRIwEAYDVQQLDAl0ZXN0ZW5kMjIxIjAgBgNV\r\n" \
    "BAMMGWNlcnRpZmljYXRlLnRlc3RlbmQyMi5jb20wggEiMA0GCSqGSIb3DQEBAQUA\r\n" \
    "A4IBDwAwggEKAoIBAQDsMC84reB0dS3CYYcSL7rj2OaE0Jqtyhuo77j9qf7jrwAG\r\n" \
    "eIuTaiCQy0L07jEtm6i8PYulVwi1ImcaIbehiPdjhv4Rx0bMZAofHHmn6ExAYphi\r\n" \
    "I1zY29Ww5pZfXmaXPaiGxmQUkntcZMPeqg4HxNm/1G5RVqGNr2gL5Vptj9pYZNvf\r\n" \
    "hWsrj7PMPFw09GJrQK2FJlQy7sxXm0ovirHXh4Z9NJfUN9VtbKNBvvWjtYnHTYPd\r\n" \
    "2nMHdE7HggcS/bWUEppFESYUSvO7kDKvOdswkDKxwJ2oVmBU0DDAUhsTorAFY8dH\r\n" \
    "bp5wNtqhCKESL7BI/ve151iVZvjU57LnjqKSwc2fAgMBAAGjTTBLMAkGA1UdEwQC\r\n" \
    "MAAwHQYDVR0OBBYEFHa3eEMeYPvYglLa6NwOuj/vSDHhMB8GA1UdIwQYMBaAFOBg\r\n" \
    "k385uwUhGUQQsMApZKK2uyMSMA0GCSqGSIb3DQEBCwUAA4IBAQB3TVit43C2LEX1\r\n" \
    "TBVyfh3386EEvqbKOKcUekzfTXagn6qkWRcEWCrRz752EdxcbjMdFcghlu7zWIhH\r\n" \
    "oLLHNvxxoXMGN9KmHKBSOG2R849aRJ+/Txe5q5zGPSB9Z4hdnsJAq/rA91elnur2\r\n" \
    "m/zLnANSZsLrZt7KkZJQ9k23yFzMtrTTsyFSAN5tsXRlU7X+++B96f0+zZ3LM56y\r\n" \
    "8LQD6nNxKpMowPfoZDK5AWaxiilKHLFVijQfbw12smsfPpuzTDhYrLPKViVmZjY4\r\n" \
    "qsHibMRjr/+tlhwAiVosgKY9l6f3ocSNjREAPuyswv7iFkF2CBsA1uykpVKELDZR\r\n" \
    "zYvWHlcn\r\n" \
    "-----END CERTIFICATE-----"

#define CLIENT_KEY_PEM \
    "-----BEGIN PRIVATE KEY-----\r\n" \
    "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDsMC84reB0dS3C\r\n" \
    "YYcSL7rj2OaE0Jqtyhuo77j9qf7jrwAGeIuTaiCQy0L07jEtm6i8PYulVwi1Imca\r\n" \
    "IbehiPdjhv4Rx0bMZAofHHmn6ExAYphiI1zY29Ww5pZfXmaXPaiGxmQUkntcZMPe\r\n" \
    "qg4HxNm/1G5RVqGNr2gL5Vptj9pYZNvfhWsrj7PMPFw09GJrQK2FJlQy7sxXm0ov\r\n" \
    "irHXh4Z9NJfUN9VtbKNBvvWjtYnHTYPd2nMHdE7HggcS/bWUEppFESYUSvO7kDKv\r\n" \
    "OdswkDKxwJ2oVmBU0DDAUhsTorAFY8dHbp5wNtqhCKESL7BI/ve151iVZvjU57Ln\r\n" \
    "jqKSwc2fAgMBAAECggEAHDkodhDBBj7iYvHzNAckFrSv3HsY9gogArCdXc0sj4SK\r\n" \
    "mjtZYm+Hc1tL+vy46lxJbi+55N4LmlQsFyv5nNdDHfo0Q2eZXDSFc8ZGpfvU8MoC\r\n" \
    "BOgji35pgKQX9U7QhONx+fjxs0uga3VXD9/ToWCygdZ0AErmhInLWHCQZ7s4OjZI\r\n" \
    "ZKMD5lTnV17ymGY1cJVRxzm2ZSLtZTB6rRFoQlrhpLGaCIqjAcvp/qpOOqtDo4Aa\r\n" \
    "9meVM2CAWRukFhZ/3/thkUd8iVHxiNq3iSwGVrPImh8wb9LYMNBNgbKNu4kjZ7dN\r\n" \
    "eMpmqRj7FRWnqpS55vqQQ4D0V9Y/UAcJHawxSLy3cQKBgQD7w5cX6iTTSbpaqMs+\r\n" \
    "mNgONLPCJznRYFIUEQcqBpYyQLbn42p+SGBvV9UX2EukhWC/SON1vjsqUXuvrB4u\r\n" \
    "Wdb5HEZaYusRmV5qLOac1zENf1RYtVvAr9SgJiCLR35W76h94YdHrjEcbjcKred8\r\n" \
    "cgKZyz16c2Aw+9KhMTwOvBS2GwKBgQDwKYFjJFz732EZmzcMiwjECgIREesTEKKW\r\n" \
    "i5sWuCYW50i0/evX4eVPOROzfBUns1fMiphr6yGzzhb+42vwwRbbpsOASQPTDHV1\r\n" \
    "e25kPqvmhiLJnMS1L9ofzYN/3S1iDrDwnHSH1HL2a/qZSE8d53Io76hpn+HkNpV0\r\n" \
    "7vZ+UguOzQKBgDVpuZSJSGbLLY4uYXBWXQAmjjySteGF3eQD+NEhtJvUvvlTdjR0\r\n" \
    "hoEY0UzNxr6QzYXHoPpJ8aN4xhTvHzgWN1WCeiqS8ew57Z35CLQds3p5mRt43o5y\r\n" \
    "v1l6vUzPTi6Dieuq/VhnzGOLvoG1g3cTeRnH1LM15yJ9SqKIH4XAwWQhAoGBAKf4\r\n" \
    "j5tU2of7c0Fikvz93TKnwUxJGP4rm1vp5p3cTB+mwe58zlAembBwPjxBo9YxlE3l\r\n" \
    "/bc1LExC70h0rZEkq6UTHReDed5Jj3mMy+fnAXnpBTm3oMkM3+VwavGqM0yq88xF\r\n" \
    "0ScTSxjY6tv8fAFxWCIThNnjTi28k4nGfLZbEeRdAoGAfu+P/UfCLfPofGjdL5Al\r\n" \
    "WC9mU/F1QRAe4C3XXJrf1A8fqRQi9cmaj+5r5gteQUzqZpnYHBZ6WLBGBE1SFGTc\r\n" \
    "EOBeTUgl0d/0rpiag2fOH9gWQibocBYZWJimjR2Y/es1N2RZc1Rkvpr42uoh1Gda\r\n" \
    "Lt4SYkYdbw3E0xDEtOZhO10=\r\n" \
    "-----END PRIVATE KEY-----"

static struct netif g_netif; // 全局网络接口

static bool send = false;


static void tls_client_err(void *arg, err_t err)
{
    (void)arg;
    printf("TLS客户端错误: %d, %s\n", err, lwip_strerr(err));
}


static err_t tls_client_recv(void *arg, struct altcp_pcb *pcb, struct pbuf *p, err_t err)
{
    (void)arg;
    (void)err;

    if (p == NULL) {
        printf("TLS客户端接收数据失败: %d\n", err);
        altcp_close(pcb);
        return ERR_OK;
    }

    printf("Received %d bytes: %s\n", p->len, (char *)p->payload);

    // 回显接收到的数据
    pbuf_free(p);
    return ERR_OK;
}

static err_t tls_client_sent(void *arg, struct altcp_pcb *pcb, u16_t len)
{
    printf("Sent %d bytes\n", len);
    
    return ERR_OK;
}

/**
 * 连接成功回调函数
 */
static err_t tls_client_connected(void *arg, struct altcp_pcb *pcb, err_t err)
{
    
    if (err != ERR_OK) {
        printf("TLS connection failed: %d\n", err);
        return err;
    }
    
    printf("TLS connection established!\n");
    
    /* 发送HTTP请求 */
    char *data = "Hello, Server!";
    altcp_write(pcb, data, strlen(data), TCP_WRITE_FLAG_COPY);
    altcp_output(pcb);

    return ERR_OK;
}

#define SERVER_IP     "192.168.100.1"
#define SERVER_PORT   8888
int main(void)
{
    struct altcp_pcb *pcb;
    struct altcp_tls_config *config;
    ip_addr_t server_ip;
    ip4_addr_t ipaddr;
    ip4_addr_t netmask;
    ip4_addr_t gw;

    tcpip_init(NULL, NULL);
    printf("LWIP初始化完成\n");

    ipaddr_aton(SERVER_IP, &server_ip);

    IP4_ADDR(&ipaddr, 192, 168, 100, 2);
    IP4_ADDR(&netmask, 255, 255, 255, 0);
    IP4_ADDR(&gw, 192, 168, 100, 1);

    /* 配置网络接口 */
    if (netif_add(&g_netif, &ipaddr, &netmask, &gw, NULL, tapif_init, tcpip_input) == NULL) {
        printf("Failed to configure network interface\n");
        return -1;
    }

    /* 启动网络接口 */
    netif_set_default(&g_netif);
    netif_set_up(&g_netif);
    netif_set_link_up(&g_netif);
    printf("网络接口启动完成\n");

    // 创建TLS客户端配置
    config = altcp_tls_create_config_client_2wayauth(CLIENT_CA_CERT_PEM, strlen(CLIENT_CA_CERT_PEM) + 1,
        CLIENT_KEY_PEM, strlen(CLIENT_KEY_PEM) + 1, NULL, 0, CLIENT_CERT_PEM, strlen(CLIENT_CERT_PEM) + 1
#ifdef LWIP_ALTCP_TLS_MBEDTLS_CRL
        , NULL, 0
#endif
#ifdef LWIP_ALTCP_TLS_MBEDTLS_AUTH_MODE
        , 1
#endif
    );
    if (config == NULL) {
        printf("Failed to create TLS client config\n");
        return -1;
    }

    pcb = altcp_tls_new(config, IPADDR_TYPE_ANY);
    if (pcb == NULL) {
        printf("Failed to create TLS client pcb\n");
        altcp_tls_free_config(config);
        return -1;
    }

    altcp_recv(pcb, tls_client_recv);
    altcp_sent(pcb, tls_client_sent);
    altcp_err(pcb, tls_client_err);

        /* 发起连接 */
    err_t err = altcp_connect(pcb, &server_ip, SERVER_PORT, tls_client_connected);
    if (err != ERR_OK) {
        printf("Failed to connect: %d\n", err);
        altcp_close(pcb);
        altcp_tls_free_config(config);
        return -1;
    }
    
    printf("Connecting to %s:%d...\n", ipaddr_ntoa(&server_ip), SERVER_PORT);

    while (1) {
        sys_check_timeouts();
        usleep(1000);
    }
    altcp_close(pcb);
    altcp_tls_free_config(config);
    return 0;
}